package ewa

import (
	"fmt"
  "io/ioutil"
  	"flag";"os";"path/filepath"
  	"strings";"path";"strconv"
  	"github.com/larspensjo/config"
      linklist "container/list"
)

var (
    name_config_file string
    subdir_config_file string
  TOPIC = make(map[string]string)
  help = flag.String("help", "", `Usage -->
    ./routine --conffname=config.ini --conffsubdir=data
    ./routine --conffname=config.ini`)
)

func CurrentDirectory() {
  var err error
  ExeDir, err = filepath.Abs(filepath.Dir(os.Args[0]))
  err=err
}


// 判断文件夹是否存在
func PathExists(path string) (bool, error) {
    _, err := os.Stat(path)
    if err == nil {
        return true, nil
    }
    if os.IsNotExist(err) {
        return false, nil
    }
    return false, err
}

func GeneratePageTemplate(srcf string, dstf string) {
  var contentByte []byte

  f, err := os.OpenFile(srcf, os.O_RDONLY,0600)
  defer f.Close()
  if err !=nil {
     l := fmt.Sprintf("Confpars/> open page source '%s' failed! %v", srcf, err); Log(l)
  } else {
    contentByte,err = ioutil.ReadAll(f)
    if err != nil {
      l := fmt.Sprintf("Confpars/> import page source '%s' failed! %v", srcf, err); Log(l)
      //fmt.Println(string(contentByte))
    }else{
      l := fmt.Sprintf("Confpars/> import page source '%s' Successfully", srcf); Log(l)
    }
  }

    f,err = os.Create(dstf)
    defer f.Close()
  if err != nil {
      l := fmt.Sprintf("Confpars/> %v", err); Log(l)
  } else {
    var content = `{{define "` + path.Base(srcf) + `"}}`
        content += "\n\n"
        content += string(contentByte)
        content += "\n\n"
        content += `{{end}}`
    _,err=f.Write([]byte(content))
    if err != nil {
      l := fmt.Sprintf("Confpars/> export page template '%s' failed! %v", dstf, err); Log(l)
    }else {
      l := fmt.Sprintf("Confpars/> export page template '%s' Successfully", dstf); Log(l)
    }
  }

}

func ConfigParser() {
  CurrentDirectory()
  cfg,err := Load_Config_File(); err=err
  //Parse_ROUTE(cfg)
  Parse_ROUTEv2(cfg)
  Parse_URL(cfg)
  Parse_RENDPAGE(cfg)
  Parse_ECHO(cfg)
  Parse_AUTH(cfg)
  Parse_REDISQ(cfg)
  Parse_MYSQL(cfg)
  Parse_LOGOPTION(cfg)
}

/*
type REDISQ struct {
  Address string
  Password string
  ApiBind string
  MApiBind map[string]string
}
*/
func PrintApiBindRedisQ() {
  l := fmt.Sprintf("Confpars/> Redis address: %s", CfgRedisQ.Address); Log(l)
  l = fmt.Sprintf("Confpars/> Redis password: %s", CfgRedisQ.Password); Log(l)
  l = fmt.Sprintf("Confpars/> Redis queue bind API: %s", CfgRedisQ.ApiBind); Log(l)
}

func ConfigPrint() {

  PrintStringArray(CfgRoute.L_NRPage)
  PrintStringArray(CfgRoute.L_RPage)
  //PrintStringArray(CfgRoute.L_CtrlEvent)
  PrintStringArray(CfgRoute.L_NRApi)
  
  //PrintStringArray(CfgUrl.L_Page)
  //PrintStringArray(CfgUrl.L_Static)

}

func Load_Config_File() (*config.Config, error) {
  exe_dir,_ := filepath.Abs(filepath.Dir(os.Args[0]))

  flag.StringVar(&name_config_file, "conffname", "config.ini", "set configuration file's name.")
  flag.StringVar(&subdir_config_file, "conffsubdir", "", "set configuration file's sub-directory.")

    flag.Parse()

    var configFile string
    if subdir_config_file != "" {
      configFile=exe_dir+"/"+subdir_config_file+"/"+name_config_file
    }else{
      configFile=exe_dir+"/"+name_config_file
    }
    l:=fmt.Sprintf("Confpars/> Loading configuration file '%s' ... ... ", configFile); Log(l)

  cfg,err := config.ReadDefault(configFile)   //读取配置文件，并返回其Config
    if err != nil {
      l=fmt.Sprintf("Confpars/> Fail to find %v,%v",configFile,err)
      Log(l)
    }else{
      l=fmt.Sprintf("Confpars/> Load '%s' Successfully. ", configFile)
      Log(l)      
    }
  return cfg, err
}

func Parse_ECHO(cfg *config.Config) {
 
    if  cfg.HasSection("ECHO") {   //判断配置文件中是否有section（一级标签）
      options,err := cfg.SectionOptions("ECHO")    //获取一级标签的所有子标签options（只有标签没有值）
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("ECHO",v)  //根据一级标签section和option获取对应的值
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "ECHO")
        Log(l)
      }
    }

    EchoPort = TOPIC["Port"]
    EchoPort = DeletePreAndSufSpace(EchoPort)
    StaticRes.Config = TOPIC["StaticRes"]

    if EchoPort == "" {
      l:=fmt.Sprintf("Confpars/> echo port is null!")
      Log(l)
    }else {
      EchoPort = ":"+EchoPort
    }

    if StaticRes.Config != "" {
      StaticRes.L_Static = strings.Split(StaticRes.Config, ","); ConfigDataNormalize( StaticRes.L_Static)

      StaticRes.ResList = linklist.New()
      for i:=0; i < len(StaticRes.L_Static); i++ {
        StaticRes.L_Static[i] = Strip(StaticRes.L_Static[i], "() \t")
        var a []string = strings.Split(StaticRes.L_Static[i], ":")
        ConfigDataNormalize(a)
        key := a[0]; value := a[1]
        Resource_ := Resource {
            HttpRoute: key,
            RealLocation: value,
        }
        StaticRes.ResList.PushBack(Resource_)
        l:=fmt.Sprintf("Confpars/> (%s) parse to key:'%s', value:'%s'", StaticRes.L_Static[i], key, value)
        Log(l)
      }

    }

}


func Parse_ROUTE(cfg *config.Config) {
      if  cfg.HasSection("ROUTE") {   //判断配置文件中是否有section（一级标签）
      options,err := cfg.SectionOptions("ROUTE")    //获取一级标签的所有子标签options（只有标签没有值）
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("ROUTE",v)  //根据一级标签section和option获取对应的值
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "ROUTE")
        Log(l)
      }
    }
    //l:=fmt.Sprintf("Confpars/> \n%s\n%s\n%s\n", TOPIC["Page"], TOPIC["CtrlEvent"], TOPIC["Api"]); Log(l)
    CfgRoute.NRPage = TOPIC["NRPage"]
    CfgRoute.RPage = TOPIC["RPage"]
    CfgRoute.CtrlEvent = TOPIC["CtrlEvent"]
    CfgRoute.NRApi = TOPIC["NRApi"]
    CfgRoute.RApi = TOPIC["RApi"]
    CfgRoute.ApiLogin = TOPIC["ApiLogin"]
    CfgRoute.ApiAddUser = TOPIC["ApiAddUser"]
    CfgRoute.ApiChangePass = TOPIC["ApiChangePass"]

    if CfgRoute.NRPage != "" {
      CfgRoute.L_NRPage = strings.Split(CfgRoute.NRPage, ","); ConfigDataNormalize(CfgRoute.L_NRPage)
    }
    if CfgRoute.RPage != "" {
      CfgRoute.L_RPage = strings.Split(CfgRoute.RPage, ","); ConfigDataNormalize(CfgRoute.L_RPage)
    }
    if CfgRoute.CtrlEvent != "" {
      CfgRoute.L_CtrlEvent = strings.Split(CfgRoute.CtrlEvent, ","); ConfigDataNormalize(CfgRoute.L_CtrlEvent)
    }
    if CfgRoute.NRApi != "" {
      CfgRoute.L_NRApi = strings.Split(CfgRoute.NRApi, ","); ConfigDataNormalize(CfgRoute.L_NRApi)
    }
    if CfgRoute.RApi != "" {
      CfgRoute.L_RApi = strings.Split(CfgRoute.RApi, ","); ConfigDataNormalize(CfgRoute.L_RApi)
    }
    if CfgRoute.ApiLogin != "" {
      CfgRoute.ApiLogin = DeletePreAndSufSpace(CfgRoute.ApiLogin)
    }
    if CfgRoute.ApiAddUser != "" {
      CfgRoute.ApiAddUser = DeletePreAndSufSpace(CfgRoute.ApiAddUser)
    }
    if CfgRoute.ApiChangePass != "" {
      CfgRoute.ApiChangePass = DeletePreAndSufSpace(CfgRoute.ApiChangePass)
    }
}

func Parse_ROUTEv2(cfg *config.Config) {
      if  cfg.HasSection("ROUTE") {   //判断配置文件中是否有section（一级标签）
      options,err := cfg.SectionOptions("ROUTE")    //获取一级标签的所有子标签options（只有标签没有值）
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("ROUTE",v)  //根据一级标签section和option获取对应的值
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "ROUTE")
        Log(l)
      }
    }
    //l:=fmt.Sprintf("Confpars/> \n%s\n%s\n%s\n", TOPIC["Page"], TOPIC["CtrlEvent"], TOPIC["Api"]); Log(l)
    CfgRoute.NRPage = TOPIC["NRPage"]
    CfgRoute.RPage = TOPIC["RPage"]
    CfgRoute.CtrlEvent = TOPIC["CtrlEvent"]
    CfgRoute.ApiAttr = TOPIC["ApiAttr"]

    CfgRoute.ApiLogin = TOPIC["ApiLogin"]
    CfgRoute.ApiAddUser = TOPIC["ApiAddUser"]
    CfgRoute.ApiChangePass = TOPIC["ApiChangePass"]

    if CfgRoute.NRPage != "" {
      CfgRoute.L_NRPage = strings.Split(CfgRoute.NRPage, ","); ConfigDataNormalize(CfgRoute.L_NRPage)
    }
    if CfgRoute.RPage != "" {
      CfgRoute.L_RPage = strings.Split(CfgRoute.RPage, ","); ConfigDataNormalize(CfgRoute.L_RPage)
    }
    if CfgRoute.CtrlEvent != "" {
      CfgRoute.L_CtrlEvent = strings.Split(CfgRoute.CtrlEvent, ","); ConfigDataNormalize(CfgRoute.L_CtrlEvent)
    }
    if CfgRoute.ApiAttr != "" {
      CfgRoute.L_ApiAttr = strings.Split(CfgRoute.ApiAttr, ","); ConfigDataNormalize(CfgRoute.L_ApiAttr)
      
      CfgRoute.MApiAttr = make(map[string]Attr)
      for i:=0; i < len(CfgRoute.L_ApiAttr); i++ {
        CfgRoute.L_ApiAttr[i] = Strip(CfgRoute.L_ApiAttr[i], "() \t")
        var a []string = strings.Split(CfgRoute.L_ApiAttr[i], ":")
        //  /tsdb_data_retention_settings: Q1
        ConfigDataNormalize(a)
        var t []string = strings.Split(a[1], ";")
        var R bool
        var S bool
        if t[0] == "NR" {
          R = false
        }else if t[0] == "R" {
          R=true
        }
        if t[1] == "S" {
          S=true
        }else if t[1] == "A" {
          S=false
        }
        Attr_ := Attr {
            Restrict: R, //bool
            SyncAck:  S,//bool
            Queue:    t[2],//string
        }
        CfgRoute.MApiAttr[a[0]] = Attr_
        l:=fmt.Sprintf("Confpars/> Http-API '%s' attributions: Restrict '%t', SyncAck '%t', Queue '%s'", a[0], 
          CfgRoute.MApiAttr[a[0]].Restrict, CfgRoute.MApiAttr[a[0]].SyncAck, CfgRoute.MApiAttr[a[0]].Queue)
        Log(l)
      }
    }

    if CfgRoute.ApiLogin != "" {
      CfgRoute.ApiLogin = DeletePreAndSufSpace(CfgRoute.ApiLogin)
    }
    if CfgRoute.ApiAddUser != "" {
      CfgRoute.ApiAddUser = DeletePreAndSufSpace(CfgRoute.ApiAddUser)
    }
    if CfgRoute.ApiChangePass != "" {
      CfgRoute.ApiChangePass = DeletePreAndSufSpace(CfgRoute.ApiChangePass)
    }
}

func Parse_URL(cfg *config.Config) {
 
    if  cfg.HasSection("URL") {   //判断配置文件中是否有section（一级标签）
      options,err := cfg.SectionOptions("URL")    //获取一级标签的所有子标签options（只有标签没有值）
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("URL",v)  //根据一级标签section和option获取对应的值
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "URL")
        Log(l)
      }
    }
    //l:=fmt.Sprintf("Confpars/> \n%s:%s\n", TOPIC["Page"], TOPIC["Static"]); Log(l)
    CfgUrl.Page = TOPIC["Page"]
    CfgUrl.Static = TOPIC["Static"]
    
    if CfgUrl.Page != "" {
      CfgUrl.L_Page = strings.Split(CfgUrl.Page, ","); ConfigDataNormalize(CfgUrl.L_Page)
    }
    if CfgUrl.Static != "" {
      CfgUrl.L_Static = strings.Split(CfgUrl.Static, ","); ConfigDataNormalize(CfgUrl.L_Static)
    }

}


func Parse_RENDPAGE(cfg *config.Config) {
 
    if  cfg.HasSection("RENDPAGE") {   //判断配置文件中是否有section（一级标签）
      options,err := cfg.SectionOptions("RENDPAGE")    //获取一级标签的所有子标签options（只有标签没有值）
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("RENDPAGE",v)  //根据一级标签section和option获取对应的值
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "RENDPAGE")
        Log(l)
      }
    }
    CfgRendPage.PageSource = TOPIC["PageSource"]
    CfgRendPage.PageSource = DeletePreAndSufSpace(CfgRendPage.PageSource)
    CfgRendPage.PageTempDir = TOPIC["PageTempDir"]
    CfgRendPage.PageTempDir = ExeDir+"/"+DeletePreAndSufSpace(CfgRendPage.PageTempDir)


    //创建Render 模板页面存放文件夹
    exist, err := PathExists(CfgRendPage.PageTempDir)
    if err != nil {
        l := fmt.Sprintf("Confpars/> get dir error! '%v'", err)
        Log(l)
    }
    if exist {
        l := fmt.Sprintf("Confpars/> page template directory '%s' exist", CfgRendPage.PageTempDir)
        Log(l)
    } else {
        //l = fmt.Sprintf("Confpars/> create page template directory[%s] ", CfgRendPage.PageTempDir); Log(l)
        err := os.Mkdir(CfgRendPage.PageTempDir, os.ModePerm)
        if err != nil {
            l := fmt.Sprintf("Confpars/> create page template directory '%s' Failed!", CfgRendPage.PageTempDir); Log(l)
        } else {
            l := fmt.Sprintf("Confpars/> create page template directory '%s' Successfully", CfgRendPage.PageTempDir); Log(l)
        }
    }

    //生成Render 模板页面文件
    for i:=0; i<len(CfgRoute.L_NRPage); i++ {
        GeneratePageTemplate(ExeDir+"/"+CfgRendPage.PageSource+`/`+CfgRoute.L_NRPage[i], 
                              CfgRendPage.PageTempDir+`/`+CfgRoute.L_NRPage[i])
    }
    for i:=0; i<len(CfgRoute.L_RPage); i++ {
        GeneratePageTemplate(ExeDir+"/"+CfgRendPage.PageSource+`/`+CfgRoute.L_RPage[i], 
                              CfgRendPage.PageTempDir+`/`+CfgRoute.L_RPage[i])
    }
}


func Parse_AUTH(cfg *config.Config) {
 
    if  cfg.HasSection("AUTH") {   //判断配置文件中是否有section（一级标签）
      options,err := cfg.SectionOptions("AUTH")    //获取一级标签的所有子标签options（只有标签没有值）
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("AUTH",v)  //根据一级标签section和option获取对应的值
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "AUTH")
        Log(l)
      }
    }

    CfgAuth.SL3File = TOPIC["SL3File"]
    CfgAuth.SL3Table = TOPIC["SL3Table"]
    
    if CfgAuth.SL3File != "" {
      CfgAuth.SL3File = ExeDir+`/`+ DeletePreAndSufSpace(CfgAuth.SL3File)
      l:=fmt.Sprintf("Confpars/> sqlite3 database file path: '%s'", CfgAuth.SL3File);Log(l)
    }
    if CfgAuth.SL3Table != "" {
      CfgAuth.SL3Table = DeletePreAndSufSpace(CfgAuth.SL3Table)
    }

}

func Parse_REDISQ(cfg *config.Config) {
 
    if  cfg.HasSection("REDISQ") {   
      options,err := cfg.SectionOptions("REDISQ")
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("REDISQ",v) 
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "REDISQ")
        Log(l)
      }
    }

    CfgRedisQ.Address = TOPIC["Address"]
    CfgRedisQ.Password = TOPIC["Password"]
    CfgRedisQ.ApiBind = TOPIC["ApiBind"]

    if CfgRedisQ.Address != "" {
      CfgRedisQ.Address = DeletePreAndSufSpace(CfgRedisQ.Address)
    }
    if CfgRedisQ.Password != "" {
      CfgRedisQ.Password = DeletePreAndSufSpace(CfgRedisQ.Password)
    }
    if CfgRedisQ.ApiBind != "" {
      CfgRedisQ.ApiBind = DeletePreAndSufSpace(CfgRedisQ.ApiBind)

      var aApiBind []string = strings.Split(CfgRedisQ.ApiBind, ",")
      CfgRedisQ.MApiBind = make(map[string]string)
      for i:=0; i < len(aApiBind); i++ {
        aApiBind[i] = Strip(aApiBind[i], "() \t")
        var bind []string = strings.Split(aApiBind[i], ":")
        //  /tsdb_data_retention_settings: Q1
        ConfigDataNormalize(bind)
        CfgRedisQ.MApiBind[bind[0]] = bind[1]
        l:=fmt.Sprintf("Confpars/> Bind API '%s' to Redis Queue '%s'", bind[0], bind[1])
        Log(l)
      }
        
    }

    _RedisConnArgs_()
}


/*
  Username string
  Password string
  Server string
  Port int
  Database string
*/
func Parse_MYSQL(cfg *config.Config) {
 
    if  cfg.HasSection("MYSQL") {   
      options,err := cfg.SectionOptions("MYSQL")
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("MYSQL",v) 
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "MYSQL")
        Log(l)
      }
    }

    var Port string
    MysqlConnArgs_.Username = TOPIC["Username"]
    MysqlConnArgs_.Password = TOPIC["Password"]
    MysqlConnArgs_.Server = TOPIC["Server"]
    Port = TOPIC["Port"]
    MysqlConnArgs_.Database = TOPIC["Database"]

    if MysqlConnArgs_.Username != "" {
      MysqlConnArgs_.Username = DeletePreAndSufSpace(MysqlConnArgs_.Username)
    }
    if MysqlConnArgs_.Password != "" {
      MysqlConnArgs_.Password = DeletePreAndSufSpace(MysqlConnArgs_.Password)
    }
    if MysqlConnArgs_.Server != "" {
      MysqlConnArgs_.Server = DeletePreAndSufSpace(MysqlConnArgs_.Server)
    }
    if Port != "" {
      Port = DeletePreAndSufSpace(Port)
    }
    if MysqlConnArgs_.Database != "" {
      MysqlConnArgs_.Database = DeletePreAndSufSpace(MysqlConnArgs_.Database)
    }
    p,_:= strconv.Atoi(Port)
    MysqlConnArgs_.Port = p
}

func Parse_LOGOPTION(cfg *config.Config) {
 
    if  cfg.HasSection("LOG") {   
      options,err := cfg.SectionOptions("LOG")
      if err == nil {
        for _,v := range options{
            optionValue,err := cfg.String("LOG",v) 
          if err == nil {
              TOPIC[v] =optionValue
            }
      }
      }else{
        l:=fmt.Sprintf("Confpars/> couldn't find [%s]", "LOG")
        Log(l)
      }
    }

    Logoption.Echorequest = TOPIC["Echorequest"]
    Logoption.Mysqlquery = TOPIC["Mysqlquery"]
    Logoption.Apichain = TOPIC["Apichain"]

    if Logoption.Echorequest != "" {
      Logoption.Echorequest = DeletePreAndSufSpace(Logoption.Echorequest)
    }
    if Logoption.Mysqlquery != "" {
      Logoption.Mysqlquery = DeletePreAndSufSpace(Logoption.Mysqlquery)
    }
    if Logoption.Apichain != "" {
      Logoption.Apichain = DeletePreAndSufSpace(Logoption.Apichain)
    }
}